
import json
import mitmproxy.http
import openpyxl
from mitmproxy import ctx
from markupsafe import soft_str

header_key = "Authorization"

url_list: list[str] = []

class Recording:

    def __init__(self, filter_url: str, filename: str = "录制.xlsx"):
        """
        基于mitmproxy抓包生成用例数据
        :param filter_url: 需要过滤的url
        :param filename: 生成用例文件路径
        """
        self.url = filter_url
        self.excel_row = [
            '编号',
            '标题',
            '是否启用',
            '用户变量',
            '前置处理脚本',
            '请求方式',
            '数据库连接信息',
            'UI驱动信息({"web/app":{}/""})',
            '请求头',
            '接口路径 or sql语句',
            '元素操作信息({($定位方式,具体路径,(显示等待信息))/"":(操作,(参数,))/"")}',
            '参数类型',
            '请求参数',
            '文件信息({参数名:[文件路径,]})',
            '提取参数({k/(k,随机,类型):v})',    #所有用例不能出现相同命名的参数,否则会影响异步执行用例
            '变量名称(多个;分开)',  #所有用例不能出现相同命名的参数,否则会影响异步执行用例
            '提取变量表达式(jsonpath/正则表达式,多个;分开)',
            '变量随机信息(0:随机/1:第一个)',
            '变量类型(str,int,float,bool)',
            '后置处理脚本',
            '断言信息',
            '预期结果',
            '实际结果模板',
            '实际结果',
            '是否通过'
        ]
        self.cases = [self.excel_row]
        self.counter = 1
        self.file = filename

    def response(self, flow: mitmproxy.http.HTTPFlow):
        """
        mitmproxy抓包处理响应，在这里汇总需要数据, 过滤 包含指定url，并且响应格式是 json的
        :param flow:
        :return:
        """
        if flow.response.status_code == 200 and self.url in flow.request.url and 'json' in flow.response.headers[
            "content-type"] and flow.request.url not in url_list:
            # 编号
            number = str(self.counter)

            # 标题
            title = "mitmproxy录制接口" + str(self.counter)

            try:
                token = flow.request.headers[header_key]
            except KeyError:
                token = ''
            header = json.dumps({header_key: token})

            # 请求地址，config.yaml 里面基准环境地址 写 空字符串
            method = flow.request.method.lower()
            url = flow.request.url
            try:
                content_type = flow.request.headers['content-type']
            except KeyError:
                content_type = ''
            if 'form' in content_type:
                param_type = "data"
            elif 'json' in content_type:
                param_type = 'json'
            else:
                if '?' in url:
                    param_type = 'query'
                else:
                    param_type = 'path'
            params = flow.request.text

            # 预期结果
            try:
                expect = json.dumps(
                    {".": json.loads(flow.response.text)}, ensure_ascii=False)
            except Exception as e:
                ctx.log.error(e)
                expect = '{}'

            # 日志
            ctx.log.info(url)
            ctx.log.info(header)
            ctx.log.info(content_type)
            ctx.log.info(method)
            ctx.log.info(params)
            ctx.log.info(flow.response.text)
            case = [
                number,
                title,
                True,
                None,
                None,
                method,
                None,
                None,
                header,
                url,
                None,
                param_type,
                params,
                None,
                None,
                None,
                None,
                None,
                None,
                None,
                None,
                None,
                None,
                flow.response.text,
                'pass'
            ]

            self.cases.append(case)
            self.counter += 1
            # 文件末尾追加
            self.excel_cases()

            url_list.append(url)

    def excel_cases(self):
        """
        对二维列表cases进行循环并将内容写入单元格中
        :return:
        """
        wb = openpyxl.Workbook()
        ws = wb.create_sheet('录制数据', 0)

        for x in range(len(self.cases)):
            for y in range(len(self.cases[x])):
                ws.cell(x + 1, y + 1, self.cases[x][y])
        try:
            wb.save(self.file)
        except Exception as e:
            print(e)

addons = [
    Recording("https://dev.tiktok.api.vodeshop.com/api/v1/")
]

"""
mitmweb -s recording.py 启动
ctrl + C 停止 并生成完整用例
"""
